package services

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math/big"
	"time"

	"blockchain-api/internal/models"
	"gorm.io/gorm"
)

// TransactionService 交易服务
type TransactionService struct {
	db *gorm.DB
}

// NewTransactionService 创建交易服务
func NewTransactionService(db *gorm.DB) *TransactionService {
	return &TransactionService{db: db}
}

// CreateTransaction 创建交易
func (s *TransactionService) CreateTransaction(req *models.CreateTransactionRequest) (*models.Transaction, error) {
	// 生成交易哈希
	txHash := s.generateTxHash(req)

	// 获取nonce（简化版本）
	nonce, err := s.getNextNonce(req.From)
	if err != nil {
		return nil, err
	}

	// 设置默认gas价格和限制
	gasPrice := req.GasPrice
	if gasPrice == "" {
		gasPrice = "1000000000" // 1 Gwei
	}

	gasLimit := req.GasLimit
	if gasLimit == 0 {
		gasLimit = 21000 // 标准转账gas限制
	}

	// 创建交易
	transaction := &models.Transaction{
		TxHash:    txHash,
		From:      req.From,
		To:        req.To,
		Amount:    req.Amount,
		GasPrice:  gasPrice,
		GasLimit:  gasLimit,
		Nonce:     nonce,
		Data:      req.Data,
		Signature: "", // 实际应用中应该进行签名
		Status:    "pending",
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	// 保存到数据库
	if err := s.db.Create(transaction).Error; err != nil {
		return nil, fmt.Errorf("failed to create transaction: %v", err)
	}

	return transaction, nil
}

// GetTransactions 获取交易列表
func (s *TransactionService) GetTransactions(limit, offset int, status string) ([]models.TransactionResponse, int64, error) {
	var transactions []models.Transaction
	var total int64

	// 构建查询
	query := s.db.Model(&models.Transaction{})
	if status != "" {
		query = query.Where("status = ?", status)
	}

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 获取交易列表
	if limit > 0 {
		query = query.Limit(limit)
	}
	if offset > 0 {
		query = query.Offset(offset)
	}

	if err := query.Order("created_at DESC").Find(&transactions).Error; err != nil {
		return nil, 0, err
	}

	// 转换为响应格式
	var responses []models.TransactionResponse
	for _, tx := range transactions {
		responses = append(responses, models.TransactionResponse{
			ID:        tx.ID,
			TxHash:    tx.TxHash,
			From:      tx.From,
			To:        tx.To,
			Amount:    tx.Amount,
			GasPrice:  tx.GasPrice,
			GasLimit:  tx.GasLimit,
			Nonce:     tx.Nonce,
			Data:      tx.Data,
			Status:    tx.Status,
			CreatedAt: tx.CreatedAt.Format("2006-01-02 15:04:05"),
		})
	}

	return responses, total, nil
}

// GetTransaction 获取单个交易
func (s *TransactionService) GetTransaction(hash string) (*models.Transaction, error) {
	var transaction models.Transaction
	if err := s.db.Where("tx_hash = ?", hash).First(&transaction).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("transaction not found")
		}
		return nil, err
	}
	return &transaction, nil
}

// GetAddressTransactions 获取地址交易历史
func (s *TransactionService) GetAddressTransactions(address string, limit, offset int) ([]models.TransactionResponse, int64, error) {
	var transactions []models.Transaction
	var total int64

	// 构建查询（发送或接收的交易）
	query := s.db.Model(&models.Transaction{}).Where("from = ? OR to = ?", address, address)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 获取交易列表
	if limit > 0 {
		query = query.Limit(limit)
	}
	if offset > 0 {
		query = query.Offset(offset)
	}

	if err := query.Order("created_at DESC").Find(&transactions).Error; err != nil {
		return nil, 0, err
	}

	// 转换为响应格式
	var responses []models.TransactionResponse
	for _, tx := range transactions {
		responses = append(responses, models.TransactionResponse{
			ID:        tx.ID,
			TxHash:    tx.TxHash,
			From:      tx.From,
			To:        tx.To,
			Amount:    tx.Amount,
			GasPrice:  tx.GasPrice,
			GasLimit:  tx.GasLimit,
			Nonce:     tx.Nonce,
			Data:      tx.Data,
			Status:    tx.Status,
			CreatedAt: tx.CreatedAt.Format("2006-01-02 15:04:05"),
		})
	}

	return responses, total, nil
}

// UpdateTransactionStatus 更新交易状态
func (s *TransactionService) UpdateTransactionStatus(hash, status string) error {
	result := s.db.Model(&models.Transaction{}).Where("tx_hash = ?", hash).Update("status", status)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("transaction not found")
	}
	return nil
}

// GetPendingTransactions 获取待处理交易
func (s *TransactionService) GetPendingTransactions() ([]models.Transaction, error) {
	var transactions []models.Transaction
	if err := s.db.Where("status = ?", "pending").Order("created_at ASC").Find(&transactions).Error; err != nil {
		return nil, err
	}
	return transactions, nil
}

// generateTxHash 生成交易哈希
func (s *TransactionService) generateTxHash(req *models.CreateTransactionRequest) string {
	// 简化的哈希生成（实际应该基于交易内容）
	data := fmt.Sprintf("%s%s%s%s%d", req.From, req.To, req.Amount, req.Data, time.Now().UnixNano())
	hash := sha256.Sum256([]byte(data))
	return hex.EncodeToString(hash[:])
}

// getNextNonce 获取下一个nonce
func (s *TransactionService) getNextNonce(address string) (uint64, error) {
	// 获取该地址的最大nonce
	var maxNonce uint64
	if err := s.db.Model(&models.Transaction{}).Where("from = ?", address).Select("COALESCE(MAX(nonce), 0)").Scan(&maxNonce).Error; err != nil {
		return 0, err
	}
	return maxNonce + 1, nil
}

// ValidateTransaction 验证交易
func (s *TransactionService) ValidateTransaction(tx *models.Transaction) error {
	// 验证金额
	amount, ok := new(big.Int).SetString(tx.Amount, 10)
	if !ok || amount.Cmp(big.NewInt(0)) <= 0 {
		return fmt.Errorf("invalid amount")
	}

	// 验证地址格式（简化版本）
	if tx.From == "" || tx.To == "" {
		return fmt.Errorf("invalid addresses")
	}

	// 验证nonce
	if tx.Nonce == 0 && tx.From != "" {
		return fmt.Errorf("invalid nonce")
	}

	return nil
}

// GetTransactionStats 获取交易统计
func (s *TransactionService) GetTransactionStats() (map[string]interface{}, error) {
	stats := make(map[string]interface{})

	// 总交易数
	var totalTxs int64
	if err := s.db.Model(&models.Transaction{}).Count(&totalTxs).Error; err != nil {
		return nil, err
	}
	stats["total_transactions"] = totalTxs

	// 待处理交易数
	var pendingTxs int64
	if err := s.db.Model(&models.Transaction{}).Where("status = ?", "pending").Count(&pendingTxs).Error; err != nil {
		return nil, err
	}
	stats["pending_transactions"] = pendingTxs

	// 已确认交易数
	var confirmedTxs int64
	if err := s.db.Model(&models.Transaction{}).Where("status = ?", "confirmed").Count(&confirmedTxs).Error; err != nil {
		return nil, err
	}
	stats["confirmed_transactions"] = confirmedTxs

	// 今日交易数
	today := time.Now().Truncate(24 * time.Hour)
	var todayTxs int64
	if err := s.db.Model(&models.Transaction{}).Where("created_at >= ?", today).Count(&todayTxs).Error; err != nil {
		return nil, err
	}
	stats["today_transactions"] = todayTxs

	return stats, nil
}
